package g2.routemaster.gui.wizards;

import g2.routemaster.gui.general.ECityCard;
import g2.routemaster.gui.general.ImageRegistry;
import g2.routemaster.model.CityCard;
import g2.routemaster.model.Hand;
import g2.routemaster.model.PlayedStack;
import g2.routemaster.model.Player;

import java.util.Iterator;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Listener;

public class PlayCardPage extends WizardPage implements Listener {
   Group boardCardsGroup;
   Group handCardsGroup;
   Button bPlayFirst;
   Button bPlayLast;
   Button bNoMoves;
   
   int numColumns = 7;

   protected PlayCardPage() {
      super("playCardPage");
      setTitle("Card");
      setDescription("Play a card");
   }

   public void createControl(Composite parent) {
      Composite composite = new Composite(parent, SWT.NONE);
      composite.setLayout(new GridLayout());

      boardCardsGroup = new Group(composite, SWT.NONE);
      boardCardsGroup.setText("Cards on Board");
      boardCardsGroup.setLayout(new GridLayout());
      boardCardsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL|GridData.HORIZONTAL_ALIGN_CENTER));

      handCardsGroup = new Group(composite, SWT.NONE);
      handCardsGroup.setText("Cards on Hand");
      GridLayout layout = new GridLayout();
      layout.numColumns = numColumns;
      handCardsGroup.setLayout(layout);
      handCardsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      
      bNoMoves = new Button(composite, SWT.TOGGLE);
      bNoMoves.setText("Just Clear My Board");
      bNoMoves.addListener(SWT.Selection, this);
      
      // update cards
      updateBoardCards();
      updateHandCards();

      // set the composite as the control for this page
      setControl(composite);
      setPageComplete(false);
   }

   void updateBoardCards(){
      if(boardCardsGroup.getChildren().length > 0){
         boardCardsGroup.getChildren()[0].dispose();
         boardCardsGroup.layout();
      }

      Composite cardsComp = new Composite(boardCardsGroup, SWT.NONE);
      GridLayout layout = new GridLayout();
      layout.numColumns = numColumns;
      cardsComp.setLayout(layout);
      cardsComp.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.FILL_HORIZONTAL));

      final CLabel selectedHand = getSelectedHandPlace();
      CityCard selectedCard = null;
      if(selectedHand != null){
         selectedCard = (CityCard)selectedHand.getData();
      }
      Player player = getPlayer();
      PlayedStack playedStack = player.getPlayedStack();
      
      Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);

      if(playedStack.sizeOfCityCard() > 0){
         
         // play as first
         if(selectedCard != null 
               && player.getSeatPlace().getBoard().canPlaceCardAsFirst(player, selectedCard)){
            final CLabel cardPlace = new CLabel(cardsComp, SWT.PUSH);
            cardPlace.setData(selectedCard);
            cardPlace.setImage(getPlaceCardImage());
            cardPlace.setCursor(handCursor);
            cardPlace.setToolTipText(selectedCard.getCity().getName());
            cardPlace.addListener(SWT.MouseDown, new Listener(){
               public void handleEvent(Event e){
                  CLabel lastPlace = getSelectedBoardLabel();
                  if(lastPlace != null){
                     lastPlace.setBackground(getUnselectedColor());
                     lastPlace.setImage(getCardImage(null));
                  }
                  
                  cardPlace.setImage(selectedHand.getImage());
                  cardPlace.setBackground(getSelectedColor());
                  selectedHand.setVisible(false);
                  statusChanged();
               }
            });
         }

         Iterator iter = playedStack.iteratorOfCityCard();
         while(iter.hasNext()){
            CityCard card = (CityCard)iter.next();
            final CLabel cardPlace = new CLabel(cardsComp, SWT.PUSH);
            cardPlace.setCursor(handCursor);
            cardPlace.setImage(getCardImage(card));
            cardPlace.setToolTipText(card.getCity().getName());
         }

         // play as last
         if(selectedCard != null
               && player.getSeatPlace().getBoard().canPlaceCardAsLast(player, selectedCard)){
            final CLabel cardPlace = new CLabel(cardsComp, SWT.PUSH);
            cardPlace.setData(selectedCard);
            cardPlace.setImage(getPlaceCardImage());
            cardPlace.setCursor(handCursor);
            cardPlace.setToolTipText(selectedCard.getCity().getName());
            cardPlace.addListener(SWT.MouseDown, new Listener(){
               public void handleEvent(Event e){
                  CLabel firstPlace = getSelectedBoardLabel();
                  if(firstPlace != null){
                     firstPlace.setBackground(getUnselectedColor());
                     firstPlace.setImage(getCardImage(null));
                  }
                  
                  cardPlace.setImage(selectedHand.getImage());
                  cardPlace.setBackground(getSelectedColor());
                  selectedHand.setVisible(false);
                  statusChanged();
               }
            });
         }
      } else {
         final CLabel cardPlace = new CLabel(cardsComp, SWT.PUSH);
         cardPlace.setData(selectedCard);
         cardPlace.setImage(getPlaceCardImage());
         cardPlace.setCursor(handCursor);
         cardPlace.setVisible(selectedCard != null);
         cardPlace.addListener(SWT.MouseDown, new Listener(){
            public void handleEvent(Event e){
               cardPlace.setImage(selectedHand.getImage());
               cardPlace.setBackground(getSelectedColor());
               selectedHand.setVisible(false);
               statusChanged();
            }
         });
      }

      boardCardsGroup.layout();
   }

   void updateHandCards(){
      Cursor handCursor = new Cursor(Display.getCurrent(), SWT.CURSOR_HAND);
      Player player = getPlayer();
      Hand hand = player.getHand();
      if(hand.sizeOfCityCard() > 0){
         Iterator iter = hand.iteratorOfCityCard();
         while(iter.hasNext()){
            CityCard card = (CityCard)iter.next();
            final CLabel cardPlace = new CLabel(handCardsGroup, SWT.PUSH);
            cardPlace.setData(card);
            cardPlace.setCursor(handCursor);
            cardPlace.setImage(getCardImage(card));
            cardPlace.setToolTipText(card.getCity().getName());
            cardPlace.addListener(SWT.MouseDown, new Listener(){
               public void handleEvent(Event e){
                  if(cardPlace.getBackground().equals(getSelectedColor())){
                     unselectPlace(cardPlace);
                  } else {
                     for(Control place : handCardsGroup.getChildren()){
                        unselectPlace((CLabel)place);
                     }
                     selectPlace(cardPlace);
                     updateBoardCards();
                  }
                  statusChanged();
               }
            });
         }
      } else {
         CLabel cardPlace = new CLabel(handCardsGroup, SWT.PUSH);
         cardPlace.setImage(getCardImage(null));
         cardPlace.setVisible(false);
      }
   }

   Image getCardImage(CityCard card){
      ECityCard city = ECityCard.UNKNOWN; 
      if(card != null){
         city = ECityCard.byNom(card.getCity().getName());
      } 
      return ImageRegistry.getCity(city);
   }

   Image getPlaceCardImage(){
      return ImageRegistry.getPlaceHere();
   }

   Player getPlayer(){
      PlayCardWizard wizard = (PlayCardWizard)getWizard();
      return wizard.player;
   }

   public boolean canFlipToNextPage(){
      return false;
   }

   public void handleEvent(Event e){
      setPageComplete(isPageComplete());
      getWizard().getContainer().updateButtons();
   }

   public void statusChanged(){
      handleEvent(null);
   }

   public boolean isPageComplete(){
      PlayCardWizard wizard = (PlayCardWizard)getWizard();

      Status status = validate();
      if (status.getSeverity() == IStatus.ERROR && !bNoMoves.getSelection()) {
         wizard.isCompleted = false;
         setErrorMessage(status.getMessage());
         return false;
      } else {
         setErrorMessage(null);
      }

      saveDataToModel();
      return true;
   }

   Status validate(){
      Status status = validatePlayed();

      if(status != null){
         return status;
      } else {
         return new Status(IStatus.OK, "not_used", 0, "", null);
      }
   }

   Status validatePlayed(){
      if(getSelectedBoardCard() == null){
         return new Status(IStatus.ERROR, "not_used", 0,
               "A card should be played.", null);
      }

      return null;
   }



   private void saveDataToModel(){
      PlayCardWizard wizard = (PlayCardWizard)getWizard();

      wizard.card = getSelectedBoardCard();
      wizard.isFirst = isPlayedFirst();
      wizard.clearBoard = bNoMoves.getSelection();
      
      wizard.isCompleted = true;
   }

   void onEnterPage(){
      PlayCardWizard wizard = (PlayCardWizard)getWizard();
      wizard.isCompleted = false;
   }

   void unselectPlace(CLabel label){
      label.setBackground(getUnselectedColor());
      label.setVisible(true);
   }

   void selectPlace(CLabel label){
      label.setBackground(getSelectedColor());
   }

   Color getSelectedColor(){
      return Display.getCurrent().getSystemColor(SWT.COLOR_YELLOW);
   }

   Color getUnselectedColor(){
      return Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
   }

   CLabel getSelectedHandPlace(){
      for(Control child : handCardsGroup.getChildren()){
         CLabel cardPlace = (CLabel)child;
         if(cardPlace.getBackground().equals(getSelectedColor())){
            return cardPlace;
         }
      }
      return null;
   }

   CityCard getSelectedBoardCard(){
      CLabel selection = getSelectedBoardLabel();
      if(selection != null){
         return (CityCard)selection.getData();
      }
      return null;
   }

   CLabel getSelectedBoardLabel(){
      for(Control child : ((Composite)boardCardsGroup.getChildren()[0]).getChildren()){
         CLabel cardPlace = (CLabel)child;
         if(cardPlace.getBackground().equals(getSelectedColor())){
            return cardPlace;
         }
      }
      return null;
   }

   boolean isPlayedFirst(){
      CLabel selection = getSelectedBoardLabel();
      if(selection != null){
         Composite comp = (Composite)boardCardsGroup.getChildren()[0];
         return comp.getChildren()[0].equals(selection);
      }
      return false;
   }

}
